using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection;
using System.IO;

namespace Common
{
    [Serializable]
    public class DBMapper<T>
    {
        public static T MapToEntity(DataTable dt)
        {
            T instance = Activator.CreateInstance<T>();
            if (dt.Rows.Count > 0)
            {
                foreach (PropertyInfo property in instance.GetType().GetProperties())
                {
                    int pos = dt.Columns.IndexOf(property.Name);
                    if (pos >= 0)
                    {
                        if (dt.Rows[0][pos] != System.DBNull.Value)
                        {
                            property.SetValue(instance, dt.Rows[0][pos], null);
                        }
                    }
                }
            }
            return instance;
        }

        public static List<T> MapToEntities(DataTable dt)
        {
            List<T> instances = Activator.CreateInstance<List<T>>();
            foreach (DataRow row in dt.Rows)
            {
                T instance = Activator.CreateInstance<T>();
                foreach (PropertyInfo property in instance.GetType().GetProperties())
                {
                    int pos = dt.Columns.IndexOf(property.Name);
                    if (pos >= 0)
                    {
                        if (row[pos] != System.DBNull.Value)
                        {
                            property.SetValue(instance, row[pos], null);
                        }
                    }
                }
                instances.Add(instance);
            }
            return instances;
        }

        public static DataTable MapToDataTable(List<T> entities)
        {
            DataTable dt = new DataTable();
          
            T instance = Activator.CreateInstance<T>();
            foreach (PropertyInfo property in instance.GetType().GetProperties())
            {
                dt.Columns.Add(property.Name, property.PropertyType);
            }

            foreach (T item in entities)
            {
                DataRow r = dt.NewRow();
                foreach (PropertyInfo property in instance.GetType().GetProperties())
                {                                        
                    r[property.Name] = instance.GetType().GetProperty(property.Name).GetValue(item, null);                    
                }
                dt.Rows.Add(r);
            }

            return dt;
        }

        public static byte[] DataTableToByteArray(DataTable dt)
        {
            MemoryStream ms = new MemoryStream();
            dt.DataSet.WriteXml(ms, XmlWriteMode.WriteSchema);

            // return stream data
            return ms.ToArray();   
        }

        public static DataTable ByteArrayToDataTable(byte[] data)
        {
            MemoryStream ms = new MemoryStream(data);
            DataSet ds = new DataSet();
            ds.ReadXml(ms);
            return ds.Tables[0];

        }
    }
}
